peekmore 0.4.0

Iterator which can peek forward multiple elements.
Documentation

peekmore

This crate introduces a multi-peekable iterator. The iterator is similar to core::iterator::Peekable. The main difference is that Peekable only allows you to peek at the next element and no further. This crate aims to take that limitation away.

The documentation can be found at docs.rs/peekmore.

Usage example:

use peekmore::PeekMore;

let iterable = [1, 2, 3, 4];
let mut iter = iterable.iter().peekmore();

// Peek at the first element.
let v1 = iter.peek();
assert_eq!(v1, Some(&&1));

// Consume the first element.
let v1c = iter.next();
assert_eq!(v1c, Some(&1));

// Peek at the second element (the element in our peek view also moved to the second element,
// since the first element was consumed.)
let v2 = iter.peek();
assert_eq!(v2, Some(&&2));

// Advance the peek view. The peek view will now be at the third element.
let _ = iter.advance_view();

// Check that it is indeed at the third element.
let v3 = iter.peek();
assert_eq!(v3, Some(&&3));

// Reset our peek view to the second element (since the first element has been consumed).
// It is the first non-consumed element.
iter.reset_view();

// Check that we are indeed at the second element again.
let v2 = iter.peek();
assert_eq!(v2, Some(&&2));

// Shift the peek view to the right twice by chaining the advance_view method.
let _ = iter.advance_view().advance_view();

// Verify that the peek view is indeed at the fourth element.
let v4 = iter.peek();
assert_eq!(v4, Some(&&4));

// Reset the view again.
iter.reset_view();

//We can also shift the peek view and peek with a single operation.
let v3 = iter.peek_next();
assert_eq!(v3, Some(&&3));

Illustrated example

The following illustrated example aims to show how peek() behaves. Here, i represents the position of the iterator (i.e. the next value that will be returned if next() is called) and j represents the position of the current peek view (i.e. the current element referenced if peek() is called).

  • start:
use peekmore::PeekMore;

// initialize our iterator
let iterable = [1, 2, 3, 4];
let mut iterator = iterable.iter().peekmore();
-----     -----      -----     -----
| 1 | --> | 2 |  --> | 3 | --> | 4 | --> None --> None --> ...
-----     -----      -----     -----
 ^
 i, j
  • call peek():
let j = iterator.peek();
assert_eq!(j, Some(&&1));
-----     -----      -----     -----
| 1 | --> | 2 |  --> | 3 | --> | 4 | --> None --> None --> ...
-----     -----      -----     -----
  ^
  i, j

peek() => Some(&&1)

  • call advance_view()
let iter = iterator.advance_view();
-----     -----      -----     -----
| 1 | --> | 2 |  --> | 3 | --> | 4 | --> None --> None --> ...
-----     -----      -----     -----
  ^         ^
  i         j
  • call peek() or peek(); peek() or peek(); peek(); peek() etc.

(The reference returned by peek() will not change, similar to the behaviour of [core::iter::Peekable::peek] In order to move to the next peekable element, we need to advance our view.)

let j = iterator.peek();
assert_eq!(j, Some(&&2));

// calling peek() multiple times doesn't shift our peek view; a reference to the same element will be returned each call.
assert_eq!(iterator.peek(), Some(&&2));
assert_eq!(iterator.peek(), Some(&&2));
-----     -----      -----     -----
| 1 | --> | 2 |  --> | 3 | --> | 4 | --> None --> None --> ...
-----     -----      -----     -----
  ^         ^
  i         j

          peek() => Some(&&2)
          peek() => Some(&&2)
          peek() => Some(&&2)  
  • call next() (i.e. advance the iterator; the first element will be consumed)
let i = iterator.next();
assert_eq!(i, Some(&1));
-----     -----      -----     -----
| 1 | --> | 2 |  --> | 3 | --> | 4 | --> None --> None --> ...
-----     -----      -----     -----
            ^
            i, j

next() => Some(&1)
  • call next(). (i.e. advance the iterator again; we'll see that the current peek view shifts with the next iterator position if the iterator consumes elements where our peek view pointed at previously (j < i))
// show that the peek view still is at element 2.
let j = iterator.peek();
assert_eq!(j, Some(&&2));

// consume the second element
let i = iterator.next();
assert_eq!(i, Some(&2));

// while our peek view was at positioned at the second element. it is now at the third,
// since the iterator consumed the second.
let j = iterator.peek();
assert_eq!(j, Some(&&3));


-----     -----      -----     -----
| 1 | --> | 2 |  --> | 3 | --> | 4 | --> None --> None --> ...
-----     -----      -----     -----
                       ^
                       i, j

          peek() => Some(&&2)
          next() => Some(&2)
                    peek() => Some(&&3)
  • Consume more elements by calling next() until we reach None:
let i = iterator.next();
assert_eq!(i, Some(&3));

let j = iterator.peek();
assert_eq!(j, Some(&&4));

let i = iterator.next();
assert_eq!(i, Some(&4));

let j = iterator.peek();
assert_eq!(j, None);

let i = iterator.next();
assert_eq!(i, None);
-----     -----      -----     -----
| 1 | --> | 2 |  --> | 3 | --> | 4 | --> None --> None --> ...
-----     -----      -----     -----
                                           ^
                                           i, j
                      
                      next() => Some(&3)
                                peek() => Some(&&4)
                                next() => Some(&4)
                                         peek() => None
                                         next() => None

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.